package com.wtwd.campus.vcom.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.wtwd.campus.common.Constants;
import com.wtwd.campus.common.RespCode;
import com.wtwd.campus.common.RespEntity;
import com.wtwd.campus.entity.DeviceInfo;
import com.wtwd.campus.entity.H5Customer;
import com.wtwd.campus.service.*;
import com.wtwd.campus.utils.CommandSendUtils;
import com.wtwd.campus.utils.Tools;
import com.wtwd.campus.vcom.common.Constant;
import com.wtwd.campus.vcom.entity.VcomH5Fence;
import com.wtwd.campus.vcom.entity.VcomLocationData;
import com.wtwd.campus.vcom.entity.VcomStudentDevice;
import com.wtwd.campus.vcom.entity.VcomWarningRecord;
import com.wtwd.campus.vcom.entity.vo.VcomH5FenceVO;
import com.wtwd.campus.vcom.service.VcomH5Service;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author: ldaoliang
 * @DateTime: 2022/1/4 10:13
 * @Description: TODO  H5的首页地址看是否跟原来一样，如果不一样则变动
 * H5用户表用原来的，customerId 用1，因为设备表威科姆的customerId为1，且原来的H5customer表的customerId 1没有在使用
 * 威科姆H5的用户的学生信息比较多，使用新表 vcom_h5_user_device表，字段按页面要求新增
 */
@Api(tags = "vcom H5")
@RestController
@RequestMapping("/vcom/h5")
public class VcomH5Controller {

    @Autowired
    private H5Service h5Service;
    @Autowired
    private RedisService redisService;
    @Autowired
    private DeviceInfoService deviceInfoService;
    @Autowired
    private LocationService locationService;
    @Autowired
    private CommandSendUtils commandSendUtils;
    @Autowired
    private VcomH5Service vcomH5Service;
    @Autowired
    private FenceInfoService fenceInfoService;

    private static final String vcomH5Address = "https://campus.geelocks.com/vcom/index.html";

    private static final Logger logger = LoggerFactory.getLogger(VcomH5Controller.class);


    /**
     * 外部app调用该接口获取登录页地址及token
     *
     * @param request
     * @return
     */
    @ApiOperation(value = "外部app调用该接口获取登录页地址及token", notes = "")
    @PostMapping("/jumpIndex")
    public RespEntity jumpIndex(@RequestBody JSONObject data, HttpServletRequest request) {
        //获取个人信息
        String appKey = data.getString("appKey");
        String imei1 = data.getString("imei");
        String imei = imei1.trim();
        data.put("imei", imei);
        String stuName = data.getString("stuName");
        String stuId = data.getString("stuId");
        String userId = data.getString("userId");
        logger.info("威科姆进入H5页面：appKey = {},imei = {},stuName = {},stuId = {},userId= {}", appKey, imei, stuName, stuId, userId);
        //校验appkey的有效性
        H5Customer h5Customer = h5Service.getH5CustomerByAppKey(appKey);
        if (h5Customer == null) {
            return new RespEntity(RespCode.FAILED);
        }
        //校验IMEI、stuId的有效性
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByImei(imei);
        /*if (StringUtils.isBlank(stuId) || deviceInfo == null || deviceInfo.getDeviceType() != 5) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }*/
        if (StringUtils.isBlank(stuId)) {
            return new RespEntity(RespCode.PARAMS_ERROR);
        }
        if (deviceInfo == null || deviceInfo.getDeviceType() != 5) {
            return new RespEntity(RespCode.DEVICE_NOT_BANK);
        }
        //进行h5客户过期时间判断
        if (System.currentTimeMillis() > h5Customer.getExpireTime()) {
            return new RespEntity(RespCode.H5_USE_TIME_EXPIRE);
        }
        //根据学生id和imei刷新h5围栏的最新绑定（围栏的绑定为学生而非设备）
        vcomH5Service.modifyVcomFenceDeviceId(deviceInfo.getDeviceId(), stuId);
        //生成token
        String token = Tools.getRamdomStr();
        //将学生信息保存到缓存中(用token保存学生id，用学生id保存用户信息)
        data.put("currToken", token);
        data.put("deviceId", deviceInfo.getDeviceId());
        redisService.setKey(token, Constant.VCOM_STUDENT_ID_PRE.concat(stuId).concat("_").concat(userId), 2, TimeUnit.HOURS);
        redisService.setKey(Constant.VCOM_STUDENT_ID_PRE.concat(stuId).concat("_").concat(userId), JSONObject.toJSONString(data), 2, TimeUnit.HOURS);
        //保存学生和设备的对应关系
        VcomStudentDevice stuDevBinding = vcomH5Service.getVcomStudentDeviceByStuId(stuId);
        if (stuDevBinding == null) {
            stuDevBinding = new VcomStudentDevice();
            stuDevBinding.setStudentId(stuId);
            stuDevBinding.setImei(imei);
            vcomH5Service.addStudentDeviceBinding(stuDevBinding);
        } else if (!stuDevBinding.getImei().equals(imei)) {
            stuDevBinding.setImei(imei);
            vcomH5Service.modifyStudentDeviceBinding(stuDevBinding);
        }
        //将没有归属学生的告警信息进行学生归属
        vcomH5Service.modifyWarningRecordStudentIdByImei(imei, stuId);
        //构建返回信息
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("indexUrl", vcomH5Address);
        jsonObject.put("accessToken", token);
        return new RespEntity(RespCode.SUCCESS, jsonObject);
    }

    /**
     * 决策跳转：单点登录、token是否失效
     *
     * @param request
     * @return
     */
    @GetMapping("/decisionJump")
    public RespEntity decisionJump(HttpServletRequest request) {
        //校验token的有效性
        String token = request.getHeader("accessToken");
        logger.info("访问token:{}",token);
        String stuIdStr = redisService.getValue(token);
        if (StringUtils.isBlank(stuIdStr) || !stuIdStr.contains(Constant.VCOM_STUDENT_ID_PRE)) {
            logger.info("token失效,跳转到未登录页面:{}",token);
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        //校验单点登录
        String value = redisService.getValue(stuIdStr);
        if (StringUtils.isBlank(value)) {
            logger.info("未登录,跳转到未登录页面");
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        JSONObject userInfo = JSONObject.parseObject(value);
        if (!token.equals(userInfo.getString("currToken"))) {
            return new RespEntity(RespCode.TOKEN_CONFLICT);
        }
        return new RespEntity(RespCode.SUCCESS);
    }


    /**
     * 获取设备最新的信息
     *
     * @param request
     * @return
     */
    @GetMapping("/getLatestDeviceMess")
    public RespEntity getLatestDeviceMess(HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer deviceId = userInfo.getInteger("deviceId");
        String imei = userInfo.getString("imei");
        logger.info("/getLatestDeviceMess:deviceId={}", deviceId);
        //查询设备信息
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByDeviceId(deviceId);
        //查询设备最新定位信息
        VcomLocationData locationData = locationService.getVcomLatestLocationData(deviceId);
        if (locationData == null) {
            return new RespEntity(RespCode.SUCCESS, null);
        }
        //构建返回信息
        boolean isOnline = deviceOnline(imei);
        Map<String, Object> result = new HashMap<>();
        result.put("isOnline", isOnline);
        result.put("location", locationData.getAddress());
        result.put("longitude", locationData.getLongitude());
        result.put("latitude", locationData.getLatitude());
        result.put("time", locationData.getLocationTime());
        result.put("battery", deviceInfo.getBattery());
        return new RespEntity(RespCode.SUCCESS, result);
    }

    /**
     * 刷新定位
     *
     * @return
     */
    @GetMapping("/refreshLocation")
    public RespEntity refreshLocation(HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        logger.info("refreshLocation param={}", JSONObject.toJSONString(userInfo));
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer deviceId = userInfo.getInteger("deviceId");
        String imei = userInfo.getString("imei").trim();
        logger.info("refreshLocation deviceId={},imei={}", deviceId, imei);
        //根据imei查询设备信息
        DeviceInfo deviceInfo = deviceInfoService.getDeviceInfoByDeviceId(deviceId);
        if (deviceInfo == null) {
            return new RespEntity(RespCode.DEVICE_NOT_EXIST);
        }
        String commandNumber = getCurTime();
        boolean isOnline = deviceOnline(imei);
        logger.info("refreshLocation deviceId={},imei={},isOnline={}", deviceId, imei, isOnline);
        if (isOnline) {
            //设备在线则进行指令下发
            boolean b = commandSendUtils.queryDeviceLocation(imei, commandNumber, Constants.H5_COMMAND_USER_ID, isOnline, false);
            if (b) {
                //查询最新设备信息并返回
                VcomLocationData locationData = locationService.getVcomLatestLocationData(deviceInfo.getDeviceId());
                if (locationData == null) {
                    return new RespEntity(RespCode.SUCCESS, null);
                }
                //构建返回信息
                Map<String, Object> result = new HashMap<>();
                result.put("isOnline", isOnline);
                result.put("location", locationData.getAddress());
                result.put("longitude", locationData.getLongitude());
                result.put("latitude", locationData.getLatitude());
                result.put("time", locationData.getLocationTime());
                result.put("battery", deviceInfo.getBattery());
                return new RespEntity(RespCode.SUCCESS, result);
            }
            return new RespEntity(RespCode.FAILED);
        }
        return new RespEntity(RespCode.DEVICE_OFF_LINE);
    }

    /**
     * 获取某个学生的电子围栏
     *
     * @param request
     * @return
     */
    @GetMapping("/getStuFenceList")
    public RespEntity getFenceInfoByDeviceId(HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        String stuId = userInfo.getString("stuId");
        logger.info("/getStuFenceList : stuId = {}" + stuId.toString());
        //根据学生id获取电子围栏
        List<VcomH5Fence> vcomFenceList = vcomH5Service.getVcomFenceListByStuId(stuId);
        //构建返回数据
        List<Map<String, Object>> result = new ArrayList<>();
        vcomFenceList.stream().forEach(e -> {
            Map<String, Object> map = new HashMap<>();
            map.put("fenceName", e.getFenceName());
            map.put("id", e.getId());
            map.put("type", e.getType());
            if (e.getType() == Constant.H5_FENCE_TYPE_CIRCLE) {
                String pointMess = e.getPointMess();
                JSONObject centerPoint = JSONObject.parseObject(pointMess);
                map.put("location", centerPoint.getString("location"));
            } else if (e.getType() == Constant.H5_FENCE_TYPE_POLYGON) {
                String pointMess = e.getPointMess();
                JSONArray pointArr = JSONObject.parseArray(pointMess);
                JSONObject setPoint = (JSONObject) pointArr.get(0);
                map.put("location", setPoint.getString("location"));
            }
            result.add(map);
        });
        return new RespEntity(RespCode.SUCCESS, result);
    }

    /**
     * 根据id删除围栏
     *
     * @param id
     * @param request
     * @return
     */
    @DeleteMapping("/delFenceById/{id}")
    public RespEntity delFenceById(@PathVariable("id") Integer id, HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        String stuId = userInfo.getString("stuId");
        logger.info("/delFenceById : id = {} ，stuId = {}", id, stuId);
        //根据id删除围栏
        Integer i = vcomH5Service.deleteFenceByIdAndStuId(id, stuId);
        return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 修改围栏
     *
     * @param data
     * @param request
     * @return
     */
    @PutMapping("/modifyFence")
    public RespEntity modifyFence(@RequestBody VcomH5FenceVO data, HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        String stuId = userInfo.getString("stuId");
        logger.info("modifyFence : vcomH5FenceVO = {}", data.toString());
        //修改围栏信息
        if (data.getType() == Constant.H5_FENCE_TYPE_CIRCLE) {
            //圆形围栏修改
            Map<String, Object> map = new HashMap<>();
            map.put("longitude", data.getLongitude());
            map.put("latitude", data.getLatitude());
            map.put("location", data.getLocation());
            map.put("radius", data.getRadius());
            data.setPointMess(JSONObject.toJSONString(map));
            data.setStuId(stuId);
            int i = vcomH5Service.modifyFenceInfo(data);
            return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
        } else {
            //todo 多边形围栏
            return new RespEntity(RespCode.SUCCESS);
        }
    }


    /**
     * 新增围栏
     *
     * @param data
     * @param request
     * @return
     */
    @PostMapping("/addFenceInfo")
    public RespEntity addFenceInfo(@RequestBody VcomH5FenceVO data, HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        String stuId = userInfo.getString("stuId");
        Integer deviceId = userInfo.getInteger("deviceId");
        logger.info("addFenceInfo : stuId = {},VcomH5FenceVO = {}", stuId, data.toString());
        //构建新增围栏信息
        int i = 0;
        if (data.getType() == Constant.H5_FENCE_TYPE_CIRCLE) {
            //新增圆形围栏
            Map<String, Object> map = new HashMap<>();
            map.put("longitude", data.getLongitude());
            map.put("latitude", data.getLatitude());
            map.put("location", data.getLocation());
            map.put("radius", data.getRadius());
            data.setPointMess(JSONObject.toJSONString(map));
            data.setStuId(stuId);
            data.setDeviceId(deviceId);
            //新增围栏
            i = vcomH5Service.addFenceInfo(data);

        } else if (data.getType() == Constant.H5_FENCE_TYPE_POLYGON) {
            //todo 多边形围栏
            i = 1;
        }
        return new RespEntity(i > 0 ? RespCode.SUCCESS : RespCode.FAILED);
    }

    /**
     * 根据id获取一个围栏的信息
     *
     * @param id
     * @param request
     * @return
     */
    @GetMapping("/getFenceInfoById")
    public RespEntity addFenceInfo(@RequestParam Integer id, HttpServletRequest request) {
        //查询一笔围栏信息
        VcomH5Fence fenceInfo = vcomH5Service.getFenceInfoById(id);
        if (fenceInfo == null) {
            return new RespEntity(RespCode.SUCCESS, null);
        }
        //构建返回信息
        VcomH5FenceVO result = new VcomH5FenceVO();
        if (fenceInfo.getType() == Constant.H5_FENCE_TYPE_CIRCLE) {
            //圆形围栏
            result.setId(fenceInfo.getId());
            result.setName(fenceInfo.getFenceName());
            String pointMess = fenceInfo.getPointMess();
            JSONObject data = JSONObject.parseObject(pointMess);
            result.setLatitude(data.getDouble("latitude"));
            result.setLongitude(data.getDouble("longitude"));
            result.setLocation(data.getString("location"));
            result.setRadius(data.getInteger("radius"));
            result.setType(fenceInfo.getType());
        } else if (fenceInfo.getType() == Constant.H5_FENCE_TYPE_POLYGON) {
            //todo 多边形围栏
        }
        return new RespEntity(RespCode.SUCCESS, result);
    }

    /**
     * 查看个人信息
     *
     * @param request
     * @return
     */
    @GetMapping("/getStuMess")
    public RespEntity getStuMess(HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Map<String, Object> map = (Map<String, Object>) JSONObject.parseObject(userInfo.toJSONString(), Map.class);
        return new RespEntity(RespCode.SUCCESS, map);
    }


    /**
     * 查看学生的告警记录
     *
     * @param request
     * @return
     */
    @GetMapping("/getWarningRecord")
    public RespEntity getWarningRecord(@RequestParam("num") Integer num, HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        String stuId = userInfo.getString("stuId");
        String stuName = userInfo.getString("stuName");
        List<VcomWarningRecord> records = vcomH5Service.getStudentWarningRecords(num, stuId);
        //整理返回数据
        List<Map<String, Object>> result = new ArrayList<>();
        records.stream().forEach(e -> {
            if (e.getType() == Constant.WARNING_SOS) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                String message = e.getMessage();
                JSONObject mess = JSONObject.parseObject(message);
                map.put("longitude", mess.getDouble("longitude"));
                map.put("latitude", mess.getDouble("latitude"));
                map.put("address", mess.getString("address"));
                map.put("title", "SOS求救");
                map.put("content", stuName.concat("求救！"));
                result.add(map);
            } else if (e.getType() == Constant.WARNING_H5_ENTER_FENCE) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                String message = e.getMessage();
                JSONObject mess = JSONObject.parseObject(message);
                String fenceName = mess.getString("fenceName");
                map.put("title", "进围栏告警");
                map.put("content", stuName.concat("进入").concat(fenceName).concat("围栏！"));
                result.add(map);
            } else if (e.getType() == Constant.WARNING_H5_LEFT_FENCE) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                String message = e.getMessage();
                JSONObject mess = JSONObject.parseObject(message);
                String fenceName = mess.getString("fenceName");
                map.put("title", "出围栏告警");
                map.put("content", stuName.concat("出").concat(fenceName).concat("围栏！"));
                result.add(map);
            } else if (e.getType() == Constant.WARNING_LOW_BATTERY) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                map.put("title", "低电量告警");
                map.put("content", stuName.concat("设备低电量告警"));
                result.add(map);
            } else if (e.getType() == Constant.WARNING_SHUT_DOWN) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                map.put("title", "关机告警");
                map.put("content", stuName.concat("设备关机告警"));
                result.add(map);
            } else if (e.getType() == Constant.WARNING_POWER_ON) {
                Map<String, Object> map = new HashMap<>();
                map.put("type", e.getType());
                map.put("time", e.getTime());
                map.put("title", "开机提醒");
                map.put("content", stuName.concat("设备开机提醒"));
                result.add(map);
            }
        });
        return new RespEntity(RespCode.SUCCESS, result);
    }

    /**
     * 获取设备的轨迹
     *
     * @param request
     * @return
     */
    @GetMapping("/getAttackByDeviceId")
    public RespEntity getAttackByDeviceId(@RequestParam("time") Long time,
                                          HttpServletRequest request) {
        //获取用户信息以及校验token
        JSONObject userInfo = getImeiAndDeviceId(request);
        if (userInfo == null) {
            return new RespEntity(RespCode.TOKEN_UNAUTHORIZED);
        }
        Integer deviceId = userInfo.getInteger("deviceId");
        logger.info("/getAttackByDeviceId : deviceId = {}  ", deviceId);
        //根据设备id和时间获取设备当天的轨迹
        List<Map<String, Object>> trackList = locationService.getDeviceTrackByDeviceIdVcom(deviceId, time);
        //数据去重
        return new RespEntity(RespCode.SUCCESS, trackList);
    }


    /**
     * 根据token获取设备imei和设备id
     *
     * @param request
     * @return
     */
    public JSONObject getImeiAndDeviceId(HttpServletRequest request) {
        String token = request.getHeader("accessToken");
        logger.info("accessToken={}", token);
        String value = redisService.getValue(token);
        if (StringUtils.isBlank(value) || !value.contains(Constant.VCOM_STUDENT_ID_PRE)) {
            return null;
        }
        String userInfoStr = redisService.getValue(value);
        if (StringUtils.isBlank(userInfoStr)) {
            return null;
        }
        JSONObject userInfo = JSONObject.parseObject(userInfoStr);
        userInfo.put("imei",userInfo.getString("imei").trim());
        return userInfo;
    }

    /**
     * 判断设备是否在线
     *
     * @param imei 设备imei
     * @return 设备是否在线
     */
    public boolean deviceOnline(String imei) {
        return redisService.hasKey(Constants.DEVICE_ONLINE_PREFIX + imei);
    }

    /**
     * 获取当前时间的时分秒（HHmmss）
     *
     * @return
     */
    public String getCurTime() {
        Date d = new Date();
        SimpleDateFormat sbf = new SimpleDateFormat("HH:mm:ss");
        String format = sbf.format(d);
        String[] split = format.split(":");
        String time = split[0].concat(split[1]).concat(split[2]);
        return time;
    }

    /**
     * 获取用户id
     *
     * @param request
     * @return
     */
    public Integer getUserId(HttpServletRequest request) {
        if (request.getHeader("Access-Token").equals("aaabbb")) {
            return 1;
        }
        String token = request.getHeader("accessToken");
        String value = redisService.getValue(token);
        if (StringUtils.isBlank(value) || !value.contains(Constants.H5_TOKEN_PREFIX)) {
            return 0;
        }
        Integer h5UserId = Integer.parseInt(value.split("_")[1]);
        return h5UserId;
    }


}
